CDS project¶

In [1]:
import numpy as np
import pandas as pd
import plotly.express as px
import matplotlib.pyplot as plt
from scipy.optimize import fsolve
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from scipy.optimize import minimize
In [2]:
df = pd.read_excel("market_data_2023 (1).xlsx", sheet_name=0)
df = df[0:11]
df = df.drop(['Date'], axis=1)
df.columns = df.iloc[0]  
df = df[1:]              
df.reset_index(drop=True, inplace=True) 
df.rename(columns={df.columns[0]: 'Maturity'}, inplace=True)
df
Out[2]:
Maturity Banco Santander Eni Ziggo Lufthansa Renault Allianz
0 0.5 24130 19570 93560 93000 73160 14840
1 1.0 30280 26840 134260 119940 83130 20110
2 2.0 40800 39600 208920 139830 150590 27430
3 3.0 51230 52190 292940 159550 215880 34670
4 4.0 61900 65310 372710 198290 273440 41520
5 5.0 72590 78210 446770 236070 327820 48290
6 7.0 85030 100980 527180 269500 395740 58350
7 10.0 95670 122460 574230 291570 413030 68860
8 20.0 106920 144560 612050 313450 430260 80010
9 30.0 115570 160360 621800 325460 436880 88960
In [3]:
fig = go.Figure()

for column in df.columns[1:]:  
    fig.add_trace(
        go.Scatter(
            x=df['Maturity'], 
            y=df[column], 
            mode='lines+markers',
            name=column,  
            marker=dict(size=6), 
            line=dict(width=1), 
            line_shape='linear'
        )
    )

# Update layout
fig.update_layout(
    title="Cds spread",
    xaxis_title="Maturity",
    yaxis_title="CDS spread",
    font=dict(family="Times New Roman", size=10, color="Black"),
    template="plotly_white",
    showlegend=True,
    yaxis=dict(range=[0, 700000])
)

fig.show()
In [4]:
def lambdas_and_gammas(maturities, delta, zcb, spread, LGD):
    n = len(maturities)
    lambdas = np.zeros(n)
    gammas = np.zeros(n)

    def objective_function(hazard_rate, i):
        cumulative_intensity =  sum(lambdas[:i] * delta[:i])
        
        protection_leg = LGD * sum(
            hazard_rate * zcb[j] * np.exp(-(cumulative_intensity))
            for j in range(i+1)
        )
        premium_leg = sum(
            spread[j] * zcb[j] * delta[j] * np.exp(-(cumulative_intensity))
            for j in range(i+1)
        )
        return (protection_leg - premium_leg) ** 2

    for i in range(n):
        result = minimize(
            objective_function, 
            x0=np.array([spread[i] * delta[i] / LGD]), 
            args=(i,),
            bounds=[(0, 3)]
        )
        lambdas[i] = result.x[0]
        gammas[i] = sum(lambdas[:i+1] * delta[:i+1])

    return lambdas, gammas
In [5]:
def survival_default(df, maturities, delta, zcb, firm_names, LGD):
    all_survival_probs = []
    all_default_probs = []
    all_hazard_rates = []

    for firm_name in firm_names:
        spread = df[firm_name] / 10000000
        lambdas, gammas = lambdas_and_gammas(maturities, delta, zcb, spread, LGD)
        
        survival_prob = [np.exp(-gamma) for gamma in gammas]
        default_prob = [1 - sp for sp in survival_prob]
        
       
        all_survival_probs.append(survival_prob)
        all_default_probs.append(default_prob)
        all_hazard_rates.append(lambdas)

    return all_survival_probs, all_default_probs, all_hazard_rates
In [18]:
def plot_results_with_plotly(df, maturities, delta, zcb, firm_names, LGD):
    
    
    all_survival_probs, all_default_probs, all_hazard_rates = survival_default(df, maturities, delta, zcb, firm_names, LGD)
    

    
    fig_survival = go.Figure()
    for i, firm_name in enumerate(firm_names):
        fig_survival.add_trace(go.Scatter(x=maturities, y=all_survival_probs[i], mode='lines+markers',
                                         name=f"{firm_name}", marker=dict(size=6),
                                          line=dict(width=1), line_dash='dash'))
    
    fig_survival.update_layout(
        title="Survival Probability",
        xaxis_title="Maturity",
        yaxis_title="Survival Probability",
        font=dict(family="Times New Roman", size=10, color="Black"),
        template="plotly_white",
        showlegend=True
    )
    fig_survival.show()

    # Plot Default Probabilities 
    fig_default = go.Figure()
    for i, firm_name in enumerate(firm_names):
        fig_default.add_trace(go.Scatter(x=maturities, y=all_default_probs[i], mode='lines+markers',
                                        name=f"{firm_name}", marker=dict(size=6), 
                                        line=dict(width=1), line_dash='dash'))
    
    fig_default.update_layout(
        title="Default Probability",
        xaxis_title="Maturity ",
        yaxis_title="Default Probability",
        font=dict(family="Times New Roman", size=10, color="Black"),
        template="plotly_white",
        showlegend=True
    )
    fig_default.show()

    # Plot Hazard Rates 
    fig_hazard = go.Figure()
    for i, firm_name in enumerate(firm_names):
        fig_hazard.add_trace(go.Scatter(x=maturities, y=all_hazard_rates[i], mode='lines+markers',
                                       name=f"{firm_name}", marker=dict(size=6), 
                                       line=dict(width=1), line_shape='linear'))
    
    fig_hazard.update_layout(
        title="Hazard Rates ",
        xaxis_title="Maturity",
        yaxis_title="Hazard Rate",
        font=dict(family="Times New Roman", size=10, color="Black"),
        template="plotly_white",
        showlegend=True
    )
    fig_hazard.show()
    
    
    
    
    
    # Create the figure
    fig_hazard = go.Figure()

    # Add step-line traces for all firms
    for i, firm_name in enumerate(firm_names):
        fig_hazard.add_trace(
            go.Scatter(
                x=maturities,
                y=all_hazard_rates[i],
                mode='lines',
                name=f"{firm_name}",
                line=dict(shape='hv', width=2),  # Use step-line style (hv)
                marker=dict(size=6)
            )
        )

    # Update layout
    fig_hazard.update_layout(
        title="Hazard Rates",
        xaxis_title="Maturity",
        yaxis_title="Hazard Rate",
        font=dict(family="Times New Roman", size=10, color="Black"),
        template="plotly_white",
        showlegend=True
    )

    # Show the figure
    fig_hazard.show()
In [19]:
zcb = pd.read_csv('ZCB_prices.csv')
zcb_filtered = zcb[zcb['Maturity'].isin(df['Maturity'])]
zcb_filtered = zcb['ZCB_price']
In [20]:
maturities = df.Maturity
delta = [0.5, 0.5, 1.0, 1.0, 1.0, 1.0, 2.0, 3.0,10.0, 10.0]
zcb = zcb_filtered
R = 0.4
LGD = 1 - R

firm_names = df.columns[1:]
plot_results_with_plotly(df, maturities, delta, zcb, firm_names, LGD)